#pragma once
#include <unistd.h>
#include <iostream>
#include <string>
#include <strings.h>
#include "Logger.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <cstdlib>
class UdpServer
{
    public:
    UdpServer(uint16_t port,const std::string& ip = ""):_sockfd(-1),_ip(ip),_port(port),_flag(false)
    {
        //手动绑定到指定ip和指定端口
        //_sockfd通过socket获取
    }

    void Init()
    {
        //顺序:socket创建套接字  初始化sockaddr_in,填充套接字的相关信息，ip地址，端口(这些是要进行网络传输的信息，必须使用网络大端序列)  bind(将信息放入套接字中)
        _sockfd = socket(AF_INET,SOCK_DGRAM,0);//网络通信，使用ad_inet,数据报模式sock_dgram,协议默认为0
        if(_sockfd < 0)
        {
            LOG(LogLevel::FATAL) << "create server socket error";
            exit(errno);
        }
        LOG(LogLevel::INFO) << "create server socket success";
        struct sockaddr_in local;
        bzero(&local,sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        // local.sin_addr.s_addr = inet_addr(_ip.c_str());//后面可以替换为任意IPbind，更具有兼容性
        local.sin_addr.s_addr = htonl(INADDR_ANY);

        //进行bind
        int ret = bind(_sockfd,(struct sockaddr*)&local,sizeof(local));
        if(ret < 0)
        {
            LOG(LogLevel::FATAL) << "bind error";
            exit(errno);
        }
        LOG(LogLevel::INFO) << "bind success";
    }

    void Start()
    {
        _flag = true;
        //服务器一旦跑起来，就是死循环
        //服务器要做什么：接收客户端发来的信息，处理后，再转发给客户端——recvfrom/sendto
        while(_flag)
        {
            char buffer[1024] = {0};//接收缓冲区
            //接收哪些：ip,端口，实际信息
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            bzero((void*)&client,sizeof(client));
            int n = recvfrom(_sockfd,(void*)buffer,sizeof(buffer),0,(struct sockaddr*)&client,&len);
            if(n < 0)
            {
                LOG(LogLevel::FATAL) << "server recvfrom error";
                exit(errno);
            }
            LOG(LogLevel::INFO) << "server recvfrom success";
            buffer[n] = 0;
            uint16_t client_port = ntohs(client.sin_port);
            std::string client_ip = inet_ntoa(client.sin_addr);
            //接收完信息后，显示信息,然后处理后回发
            LOG(LogLevel::INFO) << "[" << client_ip << ":" << client_port << "]" << "# " << buffer;

            std::string to_client = "server echo# ";
            to_client += buffer;
            int sz = sendto(_sockfd,to_client.c_str(),to_client.size(),0,(struct sockaddr*)&client,len);
            if(sz < 0)
            {
                LOG(LogLevel::FATAL) << "server sendto error";
                exit(errno);
            }
            LOG(LogLevel::INFO) << "server sendto success";
        }
    }

    void Stop()
    {
        _flag = false;
    }


    private:
        int _sockfd;
        uint16_t _port;
        std::string _ip;//number,dot形式的ipv4
        bool _flag;//运行状态标志位
};